﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;

namespace server.app
{
    public sealed class DataManager
    {
        public static Dictionary<string, comm.lib.ObjEVDefine> GetObjEVDDic(string classType, comm.lib.ObjEVType evType)
        {
            var dic = new Dictionary<string, comm.lib.ObjEVDefine>();
            try
            {
                var method = FindClassType.GetType(classType).GetMethod(comm.lib.ObjEVDefine.METHOD_NAME);
                var evDic = (Dictionary<string, comm.lib.ObjEVDefine>)method.Invoke(null, new object[] { evType });
                if (evDic.Count > 0)
                {
                    foreach (var evKey in evDic.Keys)
                    {
                        var item = evDic[evKey];
                        if (!dic.ContainsKey(evKey))
                        {
                            dic.Add(evKey, evDic[evKey]);
                        }
                        else
                        {
                            dic[evKey] = evDic[evKey];
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
            return dic;
        }
        public static void VerifyObjEV(string classType, comm.lib.ObjEVType evType, Dictionary<string, comm.lib.ObjEV> evDic)
        {
            var defineDic = GetObjEVDDic(classType, evType);
            var newDic = new Dictionary<string, comm.lib.ObjEV>();
            foreach (var dKey in defineDic.Keys)
            {
                var def = defineDic[dKey];
                var New = true;
                if (evDic.ContainsKey(dKey))
                {
                    var o = evDic[dKey];
                    if (o.Version == def.Version && o.Value != null && def.Type.IsInstanceOfType(o.Value))
                    {
                        New = false;
                        newDic.Add(dKey, o);
                    }
                }
                if (New)
                {
                    newDic.Add(dKey, new comm.lib.ObjEV
                    {
                        Value = def.Value,
                        Version = def.Version
                    });
                }
            }
            evDic.Clear();
            foreach (var key in newDic.Keys)
            {
                evDic.Add(key, newDic[key]);
            }
        }

        public static Dictionary<string, comm.lib.ObjEVDefine> GetMapObjEVDDic(comm.DefineFile defineFile, comm.objst.DMap.Data.SObj mobj)
        {
            var dobj = defineFile.GetObject(mobj.DObjectId);
            if (dobj != null)
            {
                return GetObjEVDDic(dobj.ClassType, comm.lib.ObjEVType.MAP_OBJ);
            }
            return new Dictionary<string, comm.lib.ObjEVDefine>();
        }
        public static void VerifyMapObjEV(comm.DefineFile defineFile, comm.objst.DMap.Data.SObj mobj)
        {
            var dobj = defineFile.GetObject(mobj.DObjectId);
            if (dobj != null)
            {
                VerifyObjEV(dobj.ClassType, comm.lib.ObjEVType.MAP_OBJ, mobj.EVDic);
            }
        }

        public table.Player TablePlayer
        {
            get
            {
                return (table.Player)_tableDic[typeof(table.Player).Name];
            }
        }
        public table.Unit TableUnit
        {
            get
            {
                return (table.Unit)_tableDic[typeof(table.Unit).Name];
            }
        }
        public table.Item TableItem
        {
            get
            {
                return (table.Item)_tableDic[typeof(table.Item).Name];
            }
        }
        public table.Faction TableFaction
        {
            get
            {
                return (table.Faction)_tableDic[typeof(table.Faction).Name];
            }
        }
        public table.Star TableStar
        {
            get
            {
                return (table.Star)_tableDic[typeof(table.Star).Name];
            }
        }
        public table.Backpack TableBackpack
        {
            get
            {
                return (table.Backpack)_tableDic[typeof(table.Backpack).Name];
            }
        }

        World _world = null;
        string _sqlConnStr = null;
        Dictionary<string, table.Table> _tableDic = new Dictionary<string, table.Table>();

        public DataManager(World world, string sqlConnStr)
        {
            _world = world;
            _sqlConnStr = sqlConnStr;

            _tableDic.Add(typeof(table.Player).Name, new table.Player(_world));
            _tableDic.Add(typeof(table.Unit).Name, new table.Unit(_world));
            _tableDic.Add(typeof(table.Item).Name, new table.Item(_world));
            _tableDic.Add(typeof(table.Faction).Name, new table.Faction(_world));
            _tableDic.Add(typeof(table.Star).Name, new table.Star(_world));
            _tableDic.Add(typeof(table.Backpack).Name, new table.Backpack(_world));
        }

        public void InitAllTable()
        {
            Call(sqlx =>
            {
                sqlx.BeginTxn();

                foreach (var table in _tableDic.Values)
                {
                    sqlx.ExecuteNonQuery(table.CreateTableSql());
                }

                if (_world.StarManager.InitAllTable(sqlx))
                {
                    sqlx.CommitTxn();
                }
                else
                {
                    Console.WriteLine("InitAllTable() err", comm.ConsoleColor.RED);
                }
            });
        }
        public void Call(Action<SQLx> callback)
        {
            Call<int>(sqlx =>
            {
                callback(sqlx);
                return 1;
            });
        }
        public T Call<T>(Func<SQLx, T> callback)
        {
            return SQLx.Call<T>("sqlserver", _sqlConnStr, sqlx =>
            {
                return callback(sqlx);
            });
        }

        object CreateInstance(string name, params object[] args)
        {
            object obj = null;
            string type = "";
            try
            {
                var asl = GetType().Assembly;
                type = asl.FullName.Split(',')[0] + ".lib." + name;
                obj = Activator.CreateInstance(asl.GetType(type), args);
            }
            catch (Exception ex)
            {
                Console.WriteLine(type + " " + ex.Message, comm.ConsoleColor.RED);
            }
            return obj;
        }

        public Star CreateStar(string starId)
        {
            var star = _world.DefineFile.GetStar(starId);
            if (star == null)
            {
                Console.WriteLine("starId:" + starId + " not found", comm.ConsoleColor.RED);
                return null;
            }
            try
            {
                return (Star)CreateInstance(star.ClassType, _world, starId);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message, comm.ConsoleColor.RED);
            }
            return null;
        }
        public Space CreateSpace(string mapId, string starId, string spaceId, int threadIndex, Dictionary<string, comm.objst.DMap.Data.Obj> exObjDic = null)
        {
            var map = _world.DefineFile.GetMap(mapId);
            if (map == null)
            {
                Console.WriteLine("mapId:" + mapId + " not found", comm.ConsoleColor.RED);
                return null;
            }
            try
            {
                return (Space)CreateInstance(map.ClassType, _world, mapId, starId, spaceId, threadIndex, exObjDic);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message, comm.ConsoleColor.RED);
            }
            return null;
        }
        public Object CreateObject(string dObjectId, string objectId)
        {
            var dobj = _world.DefineFile.GetObject(dObjectId);
            if (dobj == null)
            {
                Console.WriteLine("dObjId:" + dObjectId + " not found", comm.ConsoleColor.RED);
                return null;
            }
            try
            {
                return (Object)CreateInstance(dobj.ClassType, _world, dobj.ObjType, dObjectId, objectId);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message, comm.ConsoleColor.RED);
            }
            return null;
        }
        public State CreateState(Object obj, string stateId, DateTime beginTime, int dur)
        {
            var state = _world.DefineFile.GetState(stateId);
            if (state == null)
            {
                Console.WriteLine("stateId:" + stateId + " not found", comm.ConsoleColor.RED);
                return null;
            }
            try
            {
                return (State)CreateInstance(state.ClassType, _world, obj, stateId, beginTime, dur);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message, comm.ConsoleColor.RED);
            }
            return null;
        }
    }
}
